import 'package:badges/badges.dart' as badges;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:family_expense/features/account_user/services/account_group_service.dart';
import 'package:family_expense/features/account_user/services/join_account_group_request_service.dart';
import 'package:family_expense/features/account_user/widgets/account_group_user_list.dart';
import 'package:family_expense/features/account_user/widgets/account_group_user_security.dart';
import 'package:family_expense/features/account_user/widgets/join_account_group_request_list.dart';
import 'package:family_expense/features/account_user/widgets/user_basic_info.dart';
import 'package:family_expense/features/bank_card/widgets/bank_card_home.dart';
import 'package:family_expense/features/income_expense/widgets/map_footmark.dart';
import 'package:family_expense/features/income_expense_detail_type/widgets/income_expense_detail_type_home.dart';
import 'package:family_expense/features/journey/widgets/journey_home.dart';
import 'package:family_expense/features/system_setting/widgets/system_setting_home.dart';
import 'package:family_expense/shared/constants/data_sharing_key.dart'
    as constants;
import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:my_flutter_core/my_flutter_core.dart';

/// Uses [Consumer<User>] to retrieve the user info from the [FutureProvider<User>] in [MainView].
///
/// Why [Consumer<User>]? Beucase if we read the user from [AuthenticationService.currentUser] each time we always get null first.
/// Because [AuthenticationService.currentUser] returns [Future<User>].
/// That would cause the UI changes every time you view it due to async loading.
class AccountGroupUserHome extends StatefulWidget {
  const AccountGroupUserHome({super.key});

  @override
  State<AccountGroupUserHome> createState() => _AccountGroupUserHomeState();
}

class _AccountGroupUserHomeState extends State<AccountGroupUserHome> {
  final double _appBarHeight = 200.0;
  final double _leadingIconSize = 40.0;
  final AccountGroupService _accountGroupService = AccountGroupService();

  final JoinAccountGroupRequestService _joinAccountGroupRequestService =
      JoinAccountGroupRequestService();

  final EdgeInsets _contentPadding = const EdgeInsets.only(
    left: 20.0,
    top: 10.0,
    bottom: 10.0,
    right: 15.0,
  );

  int _receivedRequestCount = 0;

  // When current widget is loaded, the is current user data.
  // When the user data is returned from user basic info widget then this finaliable takes priority when the user info might be updated.
  User? _user;

  CheckAppUpdateResult? _checkAppUpdateResult;

  int? _totalIncomeExpenseCount;
  int? _totalIncomeExpenseDays;
  int? _totalUserCount;
  int? _totalBankCardCount;

  @override
  void initState() {
    super.initState();

    _loadCurrentUser();
    _queryBasicStatistics();
    _queryReeceivedRequestCount();

    _checkAppUpdateResult = DataSharing.get<CheckAppUpdateResult>(
      DataSharingKey.appCheckUpdateResult,
    );
  }

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: <Widget>[_buildAppBar(), _buildBody(context)],
    );
  }

  /// Builds app bar.
  Widget _buildAppBar() {
    return SliverAppBar(
      expandedHeight: _appBarHeight,
      pinned: true,
      flexibleSpace: FlexibleSpaceBar(
        title: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              _user?.fullName ?? '',
              overflow: TextOverflow.ellipsis,
              style: TextStyle(
                color: calculateContrastingColor(
                  Theme.of(context).appBarTheme.backgroundColor!,
                ),
              ),
            ),
            Text(
              (_user?.username?.formatMobilePhoneNumber() ?? ''),
              style: TextStyle(
                fontSize: 10.0,
                color: calculateContrastingColor(
                  Theme.of(context).appBarTheme.backgroundColor!,
                ),
              ),
            ),
          ],
        ),
        background: Stack(
          fit: StackFit.expand,
          children: [
            if (_user != null)
              Hero(
                tag: _user!.id!,
                transitionOnUserGestures: true,
                child: CachedNetworkImage(
                  imageUrl: _user!.avatarUrl!,
                  fit: BoxFit.cover,
                  height: _appBarHeight,
                ),
              ),
            // This gradient ensures that the toolbar icons are distinct
            // against the background image.
            const DecoratedBox(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  begin: Alignment(0.0, -1.0),
                  end: Alignment(0.0, -0.4),
                  colors: <Color>[Color(0x60000000), Color(0x00000000)],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  /// Builds main body.
  Widget _buildBody(BuildContext context) {
    return SliverList(
      delegate: SliverChildListDelegate(<Widget>[
        _buildBasicStatisticsInfoRow(),
        const Divider(),
        _buildMenuItemRow(),
        const Divider(),
        ListTile(
          contentPadding: _contentPadding,
          leading: Icon(
            MdiIcons.accountBoxMultiple,
            color: Colors.indigo,
            size: _leadingIconSize,
          ),
          title: Row(
            children: [
              const Text('我的邀请'),
              const SizedBox(width: 10.0),
              badges.Badge(
                showBadge: _receivedRequestCount > 0,
                badgeContent: Text(
                  '$_receivedRequestCount',
                  style: const TextStyle(fontSize: 12.0, color: Colors.white),
                ),
                badgeAnimation: const badges.BadgeAnimation.scale(),
              ),
            ],
          ),
          trailing: const ListTileNavigateNextIcon(),
          onTap: () async {
            final dataUpdated = await NavigatorHelper.push<bool>(
              context,
              const JoinAccountGroupRequestList(),
            );

            if (dataUpdated == true && mounted) {
              await _queryReeceivedRequestCount();

              // Since my might accept or reject the request, we need to update the pending count.
              final receivedRequestCountChangeNotifier =
                  DataSharing.get<SimpleChangeNotifier<int>>(
                    constants.DataSharingKey.receivedRequestCountChangeNotifier,
                  );

              receivedRequestCountChangeNotifier?.change(_receivedRequestCount);
            }
          },
        ),
        ListTile(
          contentPadding: _contentPadding,
          leading: Icon(
            Icons.map,
            color: Colors.lightBlue,
            size: _leadingIconSize,
          ),
          title: const Text('地图足迹'),
          trailing: const ListTileNavigateNextIcon(),
          onTap: () => NavigatorHelper.push(context, const MapFootmark()),
        ),
        ListTile(
          contentPadding: _contentPadding,
          leading: Icon(MdiIcons.accountCircle, size: _leadingIconSize),
          title: const Text('基本信息'),
          trailing: const ListTileNavigateNextIcon(),
          onTap: _user == null
              ? null
              : () async {
                  final user = await NavigatorHelper.push<User>(
                    context,
                    UserBasicInfo(_user!),
                  );

                  if (mounted) {
                    setState(() => _user = user);
                  }
                },
        ),
        ListTile(
          contentPadding: _contentPadding,
          leading: Icon(
            Icons.security,
            color: Colors.green,
            size: _leadingIconSize,
          ),
          title: const Text('账号安全'),
          trailing: const ListTileNavigateNextIcon(),
          onTap: () =>
              NavigatorHelper.push(context, const AccountGroupUserSecurity()),
        ),
        const Divider(),
        ListTile(
          contentPadding: _contentPadding,
          leading: Icon(
            Icons.settings,
            color: Colors.blue,
            size: _leadingIconSize,
          ),
          title: Row(
            children: [
              const Text('系统设置'),
              const SizedBox(width: 10.0),
              badges.Badge(
                showBadge: _checkAppUpdateResult?.hasUpdate == true,
                badgeAnimation: const badges.BadgeAnimation.scale(),
              ),
            ],
          ),
          trailing: const ListTileNavigateNextIcon(),
          onTap: () => NavigatorHelper.push(
            context,
            SystemSettingHome(_checkAppUpdateResult),
          ),
        ),
        const SizedBox(height: 90.0),
      ]),
    );
  }

  /// Builds text widget to display number which retrieved from remote service.
  /// That's why animation is needed.
  Widget _buildAnimatedFadeInNumberText(bool hasData, String text) {
    return AnimatedOpacity(
      opacity: hasData ? 1.0 : 0.0,
      duration: const Duration(milliseconds: 800),
      child: Text(text, style: Theme.of(context).textTheme.titleLarge),
    );
  }

  Widget _buildBasicStatisticsInfo(int? number, String label) {
    return Padding(
      padding: const EdgeInsets.all(12.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          _buildAnimatedFadeInNumberText(
            number != null,
            formatNumber(number ?? 0, decimalDigits: 0),
          ),
          const SizedBox(height: 4.0),
          Text(label, style: Theme.of(context).textTheme.bodySmall),
        ],
      ),
    );
  }

  Widget _buildBasicStatisticsInfoRow() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: [
        _buildBasicStatisticsInfo(_totalIncomeExpenseCount, '记录笔数'),
        _buildBasicStatisticsInfo(_totalIncomeExpenseDays, '记录天数'),
        _buildBasicStatisticsInfo(_totalUserCount, '用户数'),
        _buildBasicStatisticsInfo(_totalBankCardCount, '银行卡'),
      ],
    );
  }

  Widget _buildMenuItem({
    required Icon icon,
    required String label,
    required GestureTapCallback onTap,
  }) {
    return InkWell(
      onTap: onTap,
      child: Padding(
        padding: const EdgeInsets.all(12.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            icon,
            const SizedBox(height: 4.0),
            Text(label, style: Theme.of(context).textTheme.bodySmall),
          ],
        ),
      ),
    );
  }

  Widget _buildMenuItemRow() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: [
        _buildMenuItem(
          icon: Icon(
            MdiIcons.accountMultiple,
            color: Colors.cyan,
            size: _leadingIconSize,
          ),
          label: '用户列表',
          onTap: () =>
              _gotoAccountGroupUserListView(const AccountGroupUserList()),
        ),
        _buildMenuItem(
          icon: Icon(
            MdiIcons.airplane,
            color: Colors.lightBlue,
            size: _leadingIconSize,
          ),
          label: '我的旅程',
          onTap: () => NavigatorHelper.push(context, const JourneyHome()),
        ),
        _buildMenuItem(
          icon: Icon(
            Icons.credit_card,
            color: Colors.orange,
            size: _leadingIconSize,
          ),
          label: '银行卡片',
          onTap: () async {
            final dataUpdated = await NavigatorHelper.push<bool>(
              context,
              const BankCardHome(),
            );

            if (dataUpdated == true) {
              _queryBasicStatistics();
            }
          },
        ),
        _buildMenuItem(
          icon: Icon(
            MdiIcons.widgets,
            color: Colors.cyan,
            size: _leadingIconSize,
          ),
          label: '收支类别',
          onTap: () => NavigatorHelper.push(
            context,
            const IncomeExpenseDetailTypeHome(),
          ),
        ),
      ],
    );
  }

  Future<void> _gotoAccountGroupUserListView(Widget widget) async {
    final dataUpdated =
        await NavigatorHelper.push<bool>(context, widget) ?? false;

    // User might updated info that's why we need to rebuild UI.
    if (dataUpdated) {
      _user = await AuthStateService.instance.currentUser;

      _queryBasicStatistics();
    }
  }

  Future<void> _loadCurrentUser() async {
    // Loads current user from local storage.
    final res = await AuthStateService.instance.currentUser;

    if (mounted) {
      setState(() => _user = res);
    }
  }

  Future<void> _queryBasicStatistics() async {
    final res = await _accountGroupService.queryBasicStatistics();

    if (mounted) {
      setState(() {
        _totalUserCount = res['totalUserCount'];
        _totalBankCardCount = res['totalBankCardCount'];
        _totalIncomeExpenseCount = res['totalIncomeExpenseCount'];
        _totalIncomeExpenseDays = res['totalIncomeExpenseDays'];
      });
    }
  }

  Future<void> _queryReeceivedRequestCount() async {
    final res = await _joinAccountGroupRequestService.countReceived();

    if (mounted) {
      setState(() {
        _receivedRequestCount = res;
      });
    }
  }
}
